#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/7/17 20:43
# @Author  : huidong.bai
# @File    : CarPlaySession.py
# @Software: PyCharm
# @Mail    : MasterBai2018@outlook.com

import pdb
import time
from ctypes import *
from src.utils.common import method


class CARPLAY_MODE:
    NONE_TYPE = 0
    WAKEUP_DATA_TYPE = 1
    VAD_INFO_DATA_TYPE = 2
    AUDIO_DATA_TYPE = 3


# 定义回调函数类型
WAKEUP_CALLBACK = CFUNCTYPE(None, c_char_p, c_long, c_int)
VAD_CALLBACK = CFUNCTYPE(None, c_long, c_int)
AUDIO_CALLBACK = CFUNCTYPE(None, POINTER(c_char), c_int, c_int, c_long)
CARPLAY_CALLBACK = CFUNCTYPE(None, c_int, c_char_p)


# 定义callback结构体
class ESIRIHookST(Structure):
    _fields_ = [
        ("carplay_wakeup_info", WAKEUP_CALLBACK),
        ("carplay_vad_info", VAD_CALLBACK),
        ("carplay_data", AUDIO_CALLBACK),
        ("carplay_callback", CARPLAY_CALLBACK)
    ]


class CarPlaySession:
    m_engine = None
    m_library = None
    wakeup_call = None
    vad_call = None
    audio_call = None
    carplay_call = None

    def __init__(self, engine_os_path: str):
        try:
            self.m_library = cdll.LoadLibrary(engine_os_path)
            self.hooks = ESIRIHookST()
        except Exception as e:
            print(f"Load carplay sdk dynamic library error: {e}")

    def set_notify(self, wakeup_call, vad_call, audio_call, carplay_call):
        self.wakeup_call = wakeup_call
        self.vad_call = vad_call
        self.audio_call = audio_call
        self.carplay_call = carplay_call

    @method(WAKEUP_CALLBACK)
    def wakeup_callback(self, text, time_stamp, dur):
        self.wakeup_call(text, time_stamp, dur)

    @method(VAD_CALLBACK)
    def vad_callback(self, time_stamp, state):
        self.vad_call(time_stamp, state)

    @method(AUDIO_CALLBACK)
    def audio_callback(self, data, length, channelNum, time_stamp):
        self.audio_call(data[:length], length, channelNum, time_stamp)

    @method(CARPLAY_CALLBACK)
    def carplay_callback(self, code, text):
        self.carplay_call(code, text)

    def create(self, sample_rate: int, audio_format: int, mode: int, lang: str, config_path: str) -> int:
        self.hooks.carplay_wakeup_info = self.wakeup_callback
        self.hooks.carplay_vad_info = self.vad_callback
        self.hooks.carplay_data = self.audio_callback
        self.hooks.carplay_callback = self.carplay_callback

        self.m_library.create_carplay_link.restype = c_void_p
        self.m_engine = self.m_library.create_carplay_link(
            c_int(sample_rate),
            c_int(audio_format),
            c_int(mode),
            c_char_p(lang.encode()),
            c_char_p(config_path.encode()),
            pointer(self.hooks)
        )
        if self.m_engine is None:
            return -2
        return 0

    def set_carplay_status(self, status):
        return self.m_library.set_carplay_status(self.m_engine, int(status))

    def stop(self):
        self.m_library.destroy_carplay_link.argtypes = [POINTER(c_void_p)]
        ret = self.m_library.destroy_carplay_link(pointer(c_void_p(self.m_engine)))
        return ret
